/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package general;

/**
 *
 * eCOM - Adopte un Presta - Mars-Avril 2013
 * @author Kheira, Jef, William, Tuan-Long
 */
import commands.ICommand;
import context.IContext;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import tools.StringDecoupeur;



public abstract class ConsoleAbstractClass implements IConsole {
    // Contexte de l'invite de commande
    protected IContext context;	
    
    // Liste de commandes
    protected Map<String, ICommand> commands;	
    
    // Un booléen pour arrêter le thread
    private boolean arret;
    
    // Entrée standard, sortie standard et
    // sortie d'erreur
    private InputStream in;
    private PrintStream out;
    private PrintStream err;

	public ConsoleAbstractClass(IContext context) {
		this(context, System.in, System.out, System.err);
	}

	public ConsoleAbstractClass(IContext context, 
                                    InputStream is, 
                                    PrintStream out, 
                                    PrintStream err) 
        {
		this.commands = new HashMap<String, ICommand>();
		this.context = context;
		this.in = is;
		this.out = out;
		this.err = err;
	
		this.context.setCommands(commands);
	}

	@Override
	public Set<ConstantesConsole> getConstants() {
		return EnumSet.allOf(ConstantesConsole.class);
	}

	@Override
	public IContext getContext() {
		return this.context;
	}

	@Override
	public void run() {
		String banner;
		String line = null;
		BufferedReader br = null;

		if (!arret) {
			banner = (String) context.getVar(ConstantesConsole.BANNER.name());
			if (banner != null) {
				out.println(banner);
			}
			br = new BufferedReader(new InputStreamReader(this.in));
		}

		while (!arret) {
			String prompt;
			prompt = (String) context.getVar(ConstantesConsole.PROMPT.name());
			if (prompt == null) {
				prompt = "> ";
			}
			out.print(prompt);

			try {
				line = br.readLine();
				if (line == null) 
                                {
					arret = true;
					continue;
				}
			} 
                        catch (IOException ex) 
                        {
				err.println("Could not read input, please try again.");
				continue;
			}
			line = line.trim();
			if (line.length() == 0) {
				continue;
			}

			try 
                        {
				executeCommand(line);
			} 
                        catch (Exception ex) 
                        {
				ex.printStackTrace(err);
			}
		}
	}

	protected void executeCommand(String commandLine) throws Exception {
		commandLine = commandLine.trim();
		List<String> cmdTokens = StringDecoupeur.decoupeCmdLine(commandLine);
		
		ICommand command = null;
		
		if (cmdTokens.size() > 0) {
			String commandName = cmdTokens.get(0);
			command = commands.get(commandName);
		} else {
			err.println("Commande non trouvée.");
		}
		
		if (command != null) {
			command.execute(cmdTokens.subList(1, cmdTokens.size()), out, err);
		} else {
			err.println("Commande non trouvée.");
		}
	}
}
